static void

covariance and contravariance in .net 4 in 2 minutes

Published Friday 02 April 2010

"Covariance" = specified or MORE derived type

So upcasting to a more basic class in polymorphism is covariant.         
object
s = new string('a', 3);


But you couldn't do it for IEnumerables, even though it seemed safe. Well, now in .net 4 you can.

IList<string> stringList = new List<string>(); //will not compile in .net 1-3, but does in net 4
IEnumerable<object> objectList = stringList;


Trivia: since .net 1, arrays were covariant.
object[] data = new string[3];
data[0] = "s";
data[0] = 1; //no compiler error- just a runtime ArrayTypeMismatchException

Now IEnumerable<T> and IQueryable<T> are covariant

IList<Cat> cats = new List<Cat>();
//you can cast to IEnumerable (or IQueryable)
IEnumerable<Animal> pets = cats;
//but you cannot cast to the read-write classes
//IList<Animal> animals = cats; //compiler error

Covariant interfaces must be read-only (and not value types).

Contravariance = specified or LESS derived type

var cats = new List<Cat>(); //predicate is contravariant
cats.Find(HasFur); //private static bool HasFur(Animal animal) //so is IComparable
cats.Sort(SortByName); //private static int SortByName(Animal x, Animal y)


Previously: Microsoft TechDays roundup (31 Mar 2010)